home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Precision Software Appli…tions Silver Collection 1
/
Precision Software Applications Silver Collection Volume One (PSM) (1993).iso
/
demos
/
devel3.exe
/
DEMO3.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-05
|
42KB
|
1,690 lines
/* A simple user-interface demo -- Version 3 */
/* Written by Bernie Roehl, February 1992 */
/* Latest version (re)written June 1992 */
/* Contact: broehl@sunee.waterloo.edu */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h> /* toupper() */
#include <string.h> /* strrchr() */
#include <mem.h> /* memmove() */
#include <time.h> /* time(), ctime() */
#include <dos.h>
#include "rend386.h"
#include "userint.h"
#include "plg.h"
#include "segio.h"
#include "segasupp.h"
/* default screen data setup */
STEREO default_stereo = { 700, 240, 320, 55, 700, 10*65536L };
static VIEW default_view = {
0,0,-1000, /* ex,ey,ez */
0,0,0, /* pan,tilt,roll */
9*65536L, /* zoom */
1000,15000,-5000, /* lx,ly,lz */
0,319,0,200, /* left,right,top,bottom */
1,100000, /* hither, yon */
1/1.25*65536L, /* aspect ratio */
0, /* flags */
0,0 /* no offset */
}; /* don't init. matrix */
static VIEW root;
static VIEW *current_view;
static VIEW left_view, right_view;
static int v_page = 0; /* screen page swap variable */
static OBJLIST *objlist; /* the linked list of objects in the scene */
static l_x = 1000, l_y = 15000, l_z = -5000; /* light source */
static long center_d = 10000;
static long center_x = 0;
static long center_y = 0;
static long center_z = 0;
static long latitude = 0;
static long longitude = 0;
static long center_roll = 0;
static long light_d = 1000000;
int running = 1; /* non-zero until we're ready to exit */
int redraw = 1; /* non-zero if we need a redraw */
int review = 1; /* non-zero if we need to recompute current view */
int stereo_off = 0;
int swap_eyes = 0;
int mirror = 0;
extern int default_depth_sort;
int have_joystick = 0; /* non-zero if we have one or more joysticks */
joystick_data joy;
int have_mouse = 0; /* non-zero if we have a mouse */
static long spacestep = 10L; /* "granularity" of motion */
static char *in_filename = "";
#define to_rad(a) ((a) * 3.14159262 / 180.0)
#define sine(x) sin(to_rad(x/65536L))
#define cosine(x) cos(to_rad(x/65536L))
static int lastkey = 0;
static int nextolastkey = 0;
extern int rs232_port_adr;
char *progname = "demo ";
extern unsigned paint;
static char glove_filename[] = "hand.fig";
static SEGMENT *glove_seg;
static SEGMENT *glove_joints[20];
static glove_data glove_old, glove_new;
static int glove_waits = 0;
static use_glove = 0;
int fancy_background = 0; /* if set, we display a fancy background */
int reflection_pool = 0; /* if set, draw a "reflecting pool" at the bottom of the screen */
int have_logo = 0; /* if set, we have a logo */
int show_logo = 0; /* if set, show the logo (if we have one) */
void main(int argc, char *argv[])
{
OBJECT *obj, *lastobj;
void wrap(); /* wrap-up function, shuts everything down */
void joystick_calibration(), refresh_display();
unsigned getkey();
long x, y, z;
FILE *in;
int i;
if ((progname = strrchr(argv[0], '.')) != NULL) *progname = '\0';
progname = argv[0];
root = default_view;
current_view = &root;
compute_view_factors(current_view);
center_d = (default_stereo.world_scaling/65536.0) *
default_stereo.phys_convergence;
setup_render();
atexit(wrap);
objlist = new_objlist();
for (i = 1; i < argc; ++i)
{
if (argv[i][0] == '/' || argv[i][0] == '-')
{
switch(toupper(argv[i][1]))
{
case 'M': /* mirror stereo */
mirror = 1;
default_stereo.phys_screen_dist = 200;
default_stereo.phys_convergence = 700;
default_stereo.phys_screen_width = 120;
default_stereo.pixel_width = 160;
current_view->right = 159;
compute_view_factors(current_view);
center_d = (default_stereo.world_scaling/65536.0) *
default_stereo.phys_convergence;
break;
case 'R': /* swap eyes on Sega driver */
swap_eyes = 1;
break;
case 'C': /* set conv. distance */
default_stereo.phys_screen_dist = atol(argv[++i]);
compute_view_factors(current_view);
center_d = (default_stereo.world_scaling/65536.0) *
default_stereo.phys_convergence;
break;
case 'S': /* set world scale */
default_stereo.world_scaling = 65536.0*atof(argv[++i]);
compute_view_factors(current_view);
center_d = (default_stereo.world_scaling/65536.0) *
default_stereo.phys_convergence;
break;
case 'E': /* set eye spacing */
default_stereo.phys_eye_spacing = atol(argv[++i]);
break;
case 'O': /* turn off */
stereo_off = 1;
mirror = 1;
break;
case 'P': /* depth sort by polys */
default_depth_sort = DEEPEST;
break;
case 'A': /* depth sort by polys--middle */
default_depth_sort = AVERAGE;
break;
case '1': /* com 1 */
rs232_port_adr = 0x3fc;
break;
case '2': /* com 2 */
rs232_port_adr = 0x2fc;
break;
case 'G': /* enable glove */
use_glove = 1;
break;
}
}
else
{
if ((in = fopen(in_filename = argv[i], "r")) == NULL)
fprintf(stderr, "Could not open '%s'\n", argv[i]);
else
if (strstr(in_filename,".plg")) /* check if plg or fig file */
{
set_loadplg_offset(0,0,0);
set_loadplg_scale(1,1,1);
while ((obj = load_plg(in)) != NULL)
{
SEGMENT *s;
add_to_objlist(objlist, lastobj = obj);
if ((s = new_seg(NULL)) == NULL)
fprintf(stderr, "Warning: out of memory while loading an object\n");
else
{
seg_setrep(s, obj);
update_segment(s);
}
set_object_owner(obj, s);
if (spacestep < object_bounds(obj, &x, &y, &z)/5L)
spacestep = object_bounds(obj, &x, &y, &z)/5L;
}
if (load_err)
{
fprintf(stderr, "Load error: %d\n", load_err);
getkey();
}
}
else /* default: figure load at start */
{
SEGMENT *s, *readseg();
int c;
set_readseg_objlist(objlist);
if ((s = readseg(in, NULL)) == NULL)
fprintf(stderr, "Could not open '%s'\n", argv[i]);
else
update_segment(s);
}
fclose(in);
}
}
if (use_glove)
{
if ((in = fopen(glove_filename, "r")) == NULL)
fprintf(stderr, "Could not open '%s'\n", glove_filename);
else
{
SEGMENT *readseg();
set_readseg_objlist(objlist);
set_readseg_seglist(glove_joints,20);
if ((glove_seg = readseg(in, NULL)) == NULL)
fprintf(stderr, "Bad glove figure file!");
else
update_segment(glove_seg);
fclose(in);
}
}
if (enter_graphics())
{
fprintf(stderr, "Could not enter graphics mode\n");
exit(1);
}
if (use_glove)
{
glove_init(1);
if (mirror == 0)
{
init_SG_interrupt(switch_sega,glove_int_handler,6500); /* start Sega interrupt */
atexit(sega_off);
}
else
init_SG_interrupt(NULL, glove_int_handler,6500);
}
else
{
if (mirror == 0)
{
init_SG_interrupt(switch_sega,NULL,0); /* start Sega interrupt */
atexit(sega_off);
}
}
have_logo = load_logo("logo.pcx");
if ((have_mouse = mouse_init()) != 0) mouse_show(v_page);
#ifdef USE_JOYSTICK
if ((have_joystick = joystick_check()) != 0)
{
popmsg("Joystick found -- use it?");
if (toupper(getkey()) == 'Y')
{
refresh_display();
joystick_calibration(&joy);
}
else
have_joystick = 0;
refresh_display();
}
#endif
if (use_glove)
{
popmsg("Waiting for glove...");
while (!glove_ready())
if (kbhit())
{
getch();
running = 0;
exit(0);
}
refresh_display();
glove_read(&glove_old);
}
while (running)
{
int x, y;
unsigned buttons;
char c;
void glove_update();
if (have_mouse)
if (mouse_read(&x, &y, &buttons))
do_mouse(x, y, buttons);
if (have_joystick)
if (joystick_read(&joy))
do_joy(&joy);
if (bioskey(1)) {
do_key(nextolastkey=getkey());
lastkey = nextolastkey;
}
if (use_glove && glove_ready() == 0) glove_waits++;
if (use_glove) glove_update();
if (redraw)
{
refresh_display();
if (use_glove)
{
char w[20];
sprintf(w,"%d",glove_waits);
setup_hdwe(0);
printxyc(20,190,0,w);
reset_hdwe();
glove_waits = 0;
}
}
}
}
static char *closing_msg[] = {
"",
"The libraries used in this package are available on the Internet,",
"via anonymous ftp to sunee.uwaterloo.ca in pub/rend386.",
"",
"For more information, send e-mail to:",
" Bernie Roehl (broehl@sunee.uwaterloo.ca)",
" Dave Stampe (dstampe@sunee.uwaterloo.ca)",
"",
NULL};
void wrap() /* end program */
{
int i;
if (have_joystick) joystick_quit();
if (have_mouse) mouse_deinit();
exit_graphics();
reset_render();
for (i = 0; closing_msg[i]; ++i)
fprintf(stderr, "%s\n", closing_msg[i]);
exit(0);
}
/***************/
static long fbend[4] = { 0L, 30*65536L, 60*65536L, 75*65536L };
static long tbbend[4] = { -30*65536L, -37*65536L, -50*65536L, -65*65536L };
static long ttbend[4] = { 0L, 25*65536L, 50*65536L, 75*65536L };
void glove_update()
{
int fp, fm, fi, ft;
if (glove_ready == 0) return;
glove_read(&glove_new);
if (glove_new.x != glove_old.x ||
glove_new.y != glove_old.y ||
glove_new.z != glove_old.z ||
glove_new.rot != glove_old.rot ||
glove_new.fingers != glove_old.fingers )
{
glove_old = glove_new;
abs_move_segment(glove_seg,
glove_new.x*15, glove_new.y*15, glove_new.z*-100);
abs_rot_segment(glove_seg,
80*65536L, 20*65536L, (glove_new.rot-1)*-30*65536L);
ft = (glove_new.fingers >> 6) & 3;
fi = (glove_new.fingers >> 4) & 3;
fm = (glove_new.fingers >> 2) & 3;
fp = (glove_new.fingers >> 0) & 3;
abs_rot_segment(glove_joints[1], 0L,tbbend[ft],0L);
abs_rot_segment(glove_joints[2], ttbend[ft],-90*65536L,37*65536L);
abs_rot_segment(glove_joints[3], fbend[fi],0L,0L);
abs_rot_segment(glove_joints[4], fbend[fi],0L,0L);
abs_rot_segment(glove_joints[5], fbend[fm],0L,0L);
abs_rot_segment(glove_joints[6], fbend[fm],0L,0L);
abs_rot_segment(glove_joints[7], fbend[fp],0L,0L);
abs_rot_segment(glove_joints[8], fbend[fp],0L,0L);
abs_rot_segment(glove_joints[9], fbend[fp],0L,0L);
abs_rot_segment(glove_joints[10], fbend[fp],0L,0L);
g:
update_segment(glove_seg);
redraw = 1;
}
}
/***************/
void polar_compute()
{
MATRIX m,n;
long x = 0;
long y = 0;
long z = -center_d;
make_matrix(m,longitude,latitude,center_roll,0,0,0);
inverse_matrix(m,n);
matrix_point(n,&x,&y,&z);
current_view->ex = x + center_x;
current_view->ey = y + center_y;
current_view->ez = z + center_z;
x = l_x; y = l_y; z = l_z;
matrix_point(n,&x,&y,&z);
current_view->lx = x;
current_view->ly = y;
current_view->lz = z;
current_view->pan = latitude;
current_view->tilt = longitude;
current_view->roll = center_roll;
}
extern int screen_clear_color;
static int ccyc[30]={ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
14,13,12,11,10,9,8,7,6,5,4,3,2,1 };
void background(int page, int top, int bot, int color)
{
int inc = (top+(color&15))%30;
color &= 0xF0;
for(;top<=bot;top+=2)
{
clr_block(0,top,319,top+1,page,color+ccyc[inc]);
if ((++inc) == 30) inc=0;
}
}
void reflection(int page, int top, int bot, int step)
{
int src = top-step;
for( ; top <= bot; top++)
{
copy_block(page, 0, src, page, 0, top, 320, 1);
src -= step;
}
}
void refresh_display() /* now does stereo drawing */
{
if (review)
{
polar_compute();
initialize_screen_factors(current_view);
fast_view_factors(current_view);
review = 0;
}
if (stereo_off)
{
if (have_mouse) mouse_hide();
if (++v_page > 2) v_page = 0; /* use 3 pages to avoid flicker */
if (fancy_background) {
if (have_logo && show_logo)
background(v_page, 30, reflection_pool ? 160 : 199, 0xBF);
else
background(v_page, 0, reflection_pool ? 160 : 199, 0xB0);
}
else
clear_display(v_page);
if (have_logo && show_logo)
copy_block(3, 0, 0, v_page, 0, 0, 320, 30);
set_drawpage(v_page);
render(objlist, current_view);
if (reflection_pool) reflection(v_page, 160, 199, 3);
set_vidpage(v_page, 0);
if (have_mouse) mouse_show(v_page);
redraw = 0;
return;
}
if (have_mouse) mouse_hide();
v_page = v_page ^ 2;
if (mirror)
{
clear_display(v_page); /* left page */
set_drawpage(v_page);
mirr_stereo_view(current_view,&left_view,&default_stereo,LEFT_EYE);
render(objlist, &left_view);
mirr_stereo_view(current_view,&right_view,&default_stereo,RIGHT_EYE);
render(objlist, &right_view);
set_vidpage(v_page,0);
if (have_mouse) mouse_show(v_page);
}
else
{
clear_display(v_page); /* left page */
set_drawpage(v_page);
make_stereo_view(current_view,&left_view,&default_stereo,LEFT_EYE);
render(objlist, &left_view);
setup_hdwe(0);
printxyc(20,10,0,"L");
reset_hdwe();
clear_display(v_page+1); /* right page */
set_drawpage(v_page+1);
make_stereo_view(current_view,&right_view,&default_stereo,RIGHT_EYE);
render(objlist, &right_view);
setup_hdwe(0);
printxyc(300,10,0,"R");
reset_hdwe();
if (swap_eyes)
{
left_page = v_page+1; /* display them now */
right_page = v_page;
}
else
{
left_page = v_page;
right_page = v_page+1;
}
if (have_mouse) mouse_show(v_page);
}
redraw = 0;
}
#define F1 0x3B00
#define F2 0x3C00
#define F3 0x3D00
#define F4 0x3E00
#define F5 0x3F00
#define F6 0x4000
#define F7 0x4100
#define F8 0x4200
#define F9 0x4300
#define F10 0x4400
#define HOME 0x4700
#define END 0x4F00
#define PGUP 0x4900
#define PGDN 0x5100
#define LEFT 0x4B00
#define RIGHT 0x4D00
#define UP 0x4800
#define DOWN 0x5000
#define SHLEFT 0x4B01
#define SHRIGHT 0x4D01
#define SHUP 0x4801
#define SHDOWN 0x5001
#define SHPGUP 0x4901
#define SHPGDN 0x5101
#define CTRLLEFT 0x7300
#define CTRLRIGHT 0x7400
#define CTRLHOME 0x7700
#define CTRLEND 0x7500
#define CTRLPGUP 0x8400
#define CTRLPGDN 0x7600
#define ESC 0x001B
static int shifted = 0;
unsigned getkey()
{
unsigned c;
union REGS regs;
regs.h.ah = 2;
int86(0x16, ®s, ®s);
shifted = (regs.h.al & 3);
if ((c = bioskey(0)) & 0xFF) c &= 0xFF;
else if (shifted) c |= 1;
return c;
}
char *helptext[] = {
" HELP",
"ARROWS rotate around center",
"CTRL+ARROWS twist head",
"Pgup/Pgdn move in/out",
"Shift arrows move center X,Y",
"Shift Pgup/Pgdn move center Z",
"CTRL PgUp/CTRL PgDn change zoom",
"R repeats last move 100x",
"I gives information O sets options",
"0-9 set step size (0 = 10)",
"* resets to default view",
"Q quits, ? shows help",
"F1-F10 selects a view, V resizes view",
"C changes hither/yon clipping",
"D displays status information",
"L loads files, S saves files",
"F loads figure files",
"P displays color palette",
"Z does object manipulation",
NULL
};
static int stepsize = 5;
#define ANGLESTEP (2L*65536L)
do_key(unsigned int c)
{
void joystick_calibration(), disp_palette();
char buff[100];
FILE *in, *out;
long x, y, z;
int i, j;
MATRIX m,n;
switch (c)
{
case LEFT:
latitude -= stepsize * ANGLESTEP;
review = redraw = 1;
break;
case RIGHT:
latitude += stepsize * ANGLESTEP;
review = redraw = 1;
break;
case UP:
longitude += stepsize * ANGLESTEP;
review = redraw = 1;
break;
case DOWN:
longitude -= stepsize * ANGLESTEP;
review = redraw = 1;
break;
case SHLEFT:
x = stepsize*spacestep/10;
y = 0;
review = redraw = 1;
goto fixcenter;
case SHRIGHT:
x = -stepsize*spacestep/10 ;
y = 0;
review = redraw = 1;
goto fixcenter;
case SHUP:
y = -stepsize*spacestep/10;
x = 0;
review = redraw = 1;
goto fixcenter;
case SHDOWN:
y = stepsize*spacestep/10;
x = 0;
review = redraw = 1;
fixcenter:
z = 0;
make_matrix(m,longitude,latitude,center_roll,0,0,0);
inverse_matrix(m, n);
matrix_point(n,&x,&y,&z);
center_x += x;
center_y += y;
center_d -= z;
break;
case SHPGUP:
center_z += stepsize*spacestep/10;
review = redraw = 1;
break;
case SHPGDN:
center_z -= stepsize*spacestep/10;
review = redraw = 1;
break;
case CTRLLEFT:
center_roll -= stepsize * ANGLESTEP;
review = redraw = 1;
break;
case CTRLRIGHT:
center_roll += stepsize * ANGLESTEP;
review = redraw = 1;
break;
case PGUP:
center_d += (stepsize * spacestep);
review = redraw = 1;
break;
case PGDN:
center_d -= (stepsize * spacestep);
review = redraw = 1;
break;
case CTRLPGUP:
if (stereo_off)
current_view->zoom *= 1.1;
else
{
default_stereo.world_scaling *= 1.1;
center_d = (default_stereo.world_scaling/65536.0) *
default_stereo.phys_convergence;
}
review = redraw = 1;
break;
case CTRLPGDN:
if (stereo_off)
current_view->zoom /= 1.1;
else
{
default_stereo.world_scaling /= 1.1;
if (default_stereo.world_scaling <= 10)
default_stereo.world_scaling = 11;
center_d = (default_stereo.world_scaling/65536.0) *
default_stereo.phys_convergence;
}
review = redraw = 1;
break;
case 'U': case 'u':
current_view->pan += 180*65536L;
nextolastkey = 0;
review = redraw = 1;
break;
case '*':
current_view = &default_view;
center_d = (default_stereo.world_scaling/65536.0) *
default_stereo.phys_convergence;
center_x = 0;
center_y = 0;
center_z = 0;
latitude = 0;
longitude = 0;
center_roll = 0;
nextolastkey = 0;
review = redraw = 1;
break;
case '0': stepsize = 10; break;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
nextolastkey = 0;
stepsize = c - '0';
break;
case 'Q': case 'q': case ESC:
nextolastkey = 0;
popmsg("Really quit?");
if (toupper(getkey()) == 'Y') running = 0; else redraw = 1;
break;
case 'R': case 'r':
nextolastkey = lastkey;
if (lastkey)
for (i = 0; i < 100; i++) {
do_key(lastkey);
refresh_display();
}
break;
case 'C': case 'c':
nextolastkey = 0;
popmsg("Change Hither or Yon?");
switch (toupper(getkey()))
{
case 'H':
askfor("Enter hither value:", buff, 10);
if (buff[0])
current_view->hither = atof(buff);
if (current_view->hither < 1) current_view->hither = 1;
review = 1;
break;
case 'Y':
askfor("Enter yon value:", buff, 10);
if (buff[0]) current_view->yon = atof(buff);
review = 1;
break;
default: break;
}
redraw = 1;
break;
case 'D': case 'd':
nextolastkey = 0;
disp_status(current_view); redraw = 1; break;
case 'L': case 'l':
nextolastkey = 0;
askfor("File to load? ", buff, 15);
if (buff[0] == '\0') {
redraw = 1;
break;
}
if ((in = fopen(buff, "r")) == NULL) {
popmsg("Could not load file");
getkey();
}
else {
OBJECT *obj;
set_loadplg_offset(0,0,0);
set_loadplg_scale(1,1,1);
while ((obj = load_plg(in)) != NULL) {
SEGMENT *s;
add_to_objlist(objlist, obj);
if ((s = new_seg(NULL)) == NULL) {
popmsg("Warning -- out of memory!");
getkey();
}
else {
seg_setrep(s, obj);
update_segment(s);
}
set_object_owner(obj, s);
if (spacestep < object_bounds(obj, &x, &y, &z)/5L)
spacestep = object_bounds(obj, &x, &y, &z)/5L;
}
fclose(in);
}
redraw = 1;
break;
case 'S': case 's':
nextolastkey = 0;
askfor("File to save? ", buff, 15);
if (buff[0] == '\0') {
redraw = 1;
break;
}
if ((out = fopen(buff, "w")) == NULL) {
popmsg("Could not open file");
getkey();
}
else {
OBJECT *obj;
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
save_plg(obj, out);
fclose(out);
}
redraw = 1;
break;
case 'Z': case 'z':
nextolastkey = 0;
advanced();
while (bioskey(1)) bioskey(0); /* flush keyboard buffer */
redraw = 1; break;
case 'I': case 'i':
nextolastkey = 0; disp_info(objlist); redraw = 1; break;
case 'P': case 'p':
nextolastkey = 0; disp_palette(); getkey(); redraw = 1; break;
case 'F': case 'f':
nextolastkey = 0;
askfor("Figure file to read? ", buff, 15);
if (buff[0] == '\0') {
redraw = 1;
break;
}
if ((in = fopen(buff, "r")) == NULL) {
popmsg("Could not load figure file");
getkey();
}
else {
SEGMENT *s, *readseg();
int c;
while ((c = getc(in)) != '{')
if (c == EOF) {
popmsg("Early EOF!");
getkey();
redraw = 1;
break;
}
set_readseg_objlist(objlist);
if ((s = readseg(in, NULL)) == NULL) {
popmsg("Error reading figure file");
getkey();
}
else
update_segment(s);
}
redraw = 1;
break;
case 'H': case 'h': case '?':
nextolastkey = 0;
poptext(helptext);
getkey();
redraw = 1;
break;
case 'O': case 'o':
nextolastkey = 0;
set_options();
redraw = 1;
break;
case 'V': case 'v':
nextolastkey = 0;
resize_viewport();
review = redraw = 1;
break;
case 'X': case 'x':
nextolastkey = 0;
new_features();
while (bioskey(1)) bioskey(0); /* flush keyboard buffer */
review = redraw = 1;
break;
case '^': save_pcx_file();
default: break;
}
return 0;
}
do_joy(joystick_data *joy)
{
long dist = spacestep*stepsize;
float cosvalue, sinvalue;
if (abs(joy->x) < 10 && abs(joy->y) < 10) return 0;
cosvalue = cosine(current_view->pan);
sinvalue = sine(current_view->pan);
switch (joy->buttons)
{
case 0: /* no buttons down */
current_view->pan += (joy->x * ANGLESTEP*stepsize)/100;
current_view->ex -= (joy->y * dist * sinvalue)/100;
current_view->ez -= (joy->y * dist * cosvalue)/100;
review = redraw = 1;
break;
case 1: /* first button down */
current_view->ey -= (joy->y * spacestep*stepsize)/100;
current_view->ex -= (joy->x * dist * cosvalue)/100;
current_view->ez -= (joy->x * dist * sinvalue)/100;
review = redraw = 1;
break;
case 2: /* second button down */
current_view->tilt += (joy->y * ANGLESTEP*stepsize)/100;
current_view->roll += (joy->x * ANGLESTEP*stepsize)/100;
review = redraw = 1;
break;
case 3: /* both buttons down */
current_view->zoom += (joy->y*65536L) / 100;
review = redraw = 1;
break;
default: break;
}
return 0;
}
static char *adv_menu[] = {
"Move",
"Rotate",
"Twirl",
"Alter",
"Paint",
"Info",
"Save",
"Copy",
"Delete",
"Unselect",
"Hack off",
"Join to",
"Figure...",
NULL
};
#include "pointer.h"
POINTER pointer;
static char *surface_menu[] = { "Normal", "Cosine-lit", "Metal", "Glass", NULL };
static char *figure_menu[] = {
"Figure select",
"Delete",
"Save",
"Copy",
"Info",
NULL
};
void select_tree(SEGMENT *s)
{
SEGMENT *p; OBJECT *obj;
if ((obj = seg_getrep(s)) != NULL) highlight_obj(obj);
for (p = child_segment(s); p; p = sibling_segment(p))
select_tree(p);
}
void count_tree(SEGMENT *s, int *nsegs, int *nverts, int *npolys)
{
SEGMENT *p; OBJECT *obj;
++*nsegs;
if ((obj = seg_getrep(s)) != NULL) {
int nv, np;
get_obj_info(obj, &nv, &np, NULL, 0);
*nverts += nv; *npolys += np;
}
for (p = child_segment(s); p; p = sibling_segment(p))
count_tree(p, nsegs, nverts, npolys);
}
static void zap_obj(OBJECT *obj)
{
remove_from_objlist(objlist, obj);
delete_obj(obj);
}
static OBJECT *dup_obj(OBJECT *obj, void *owner)
{
char buff[500];
OBJECT *o;
int nv, np;
get_obj_info(obj, &nv, &np, buff, sizeof(buff));
o = copy_obj(obj, nv, np, buff);
if (o) {
add_to_objlist(objlist, o);
set_object_owner(o, owner);
unhighlight_obj(o);
}
return o;
}
advanced()
{
OBJECT *obj;
SEGMENT *s, *newparent;
void pointer_to_world();
int nsegs = 0, nobjs = 0, nverts = 0, npolys = 0, nselected = 0;
unsigned surf;
char buff[100], *p;
FILE *out;
char c, d;
long oldx, oldy, oldz, oldcx, oldcy, oldcz, dx, dy, dz;
unsigned char oldflags;
int mx, my;
unsigned buttons;
time_t now;
pointer.port = 0;
pointer.gesture = pointer.buttons = 0;
pointer.x = pointer.y = pointer.z = 0;
pointer.pan = pointer.tilt = pointer.roll = 0;
pointer.sx = pointer.sy = pointer.sz = 1;
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
++nselected;
if (nselected == 0)
{
popmsg("No objects selected!");
delay(600);
return 0;
}
poptext(adv_menu);
switch (c = toupper(getkey()))
{
case 'S':
refresh_display();
if (askfor("Enter filename: ", buff, 20) == 0x1B) break;
if (buff[0] == '\0') {
redraw = 1;
break;
}
if ((out = fopen(buff, "w")) == NULL)
{
popmsg("Could not create file");
getkey();
break;
}
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
{
if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
{
save_plg(obj, out);
sprintf(buff, "%d object%s saved", ++nobjs,
(nobjs > 1) ? "s" : "");
refresh_display();
popmsg(buff);
}
}
refresh_display();
sprintf(buff, "Saved %d object%s", nobjs, (nobjs > 1) ? "s" : "");
popmsg(buff);
getkey();
fclose(out);
break;
case 'I':
refresh_display();
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
{
char buff[100];
int nv, np;
++nobjs;
get_obj_info(obj, &nv, &np, buff, sizeof(buff)-1);
nverts += nv;
npolys += np;
}
sprintf(buff, "%d obj%s, %d vertices, %d polygon%s", nobjs, (nobjs > 1) ? "s" : "", nverts, npolys, (npolys > 1) ? "s" : "");
popmsg(buff); getkey();
break;
case 'M':
refresh_display();
pointer_read(&pointer);
oldcx = pointer.x; oldcy = pointer.y; oldcz = pointer.z;
pointer_to_world(&pointer, current_view, &oldx, &oldy, &oldz);
while ((pointer.buttons & 0x01) == 0)
{
long x, y, z;
pointer_to_world(&pointer, current_view, &x, &y, &z);
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
if (get_obj_flags(obj) & OBJ_HIGHLIGHTED) {
SEGMENT *s;
if ((s = get_object_owner(obj)) != NULL) {
rel_move_segment(s, x - oldx, y - oldy, z - oldz);
update_segment(s);
}
}
refresh_display();
oldx = x; oldy = y; oldz = z;
pointer_read(&pointer);
}
while (pointer.buttons & 0x01) pointer_read(&pointer);
refresh_display();
break;
case 'R':
case 'T':
refresh_display();
pointer_read(&pointer);
oldcx = oldx = pointer.x;
oldcy = oldy = pointer.y;
oldcz = oldz = pointer.z;
while ((pointer.buttons & 0x01) == 0)
{
long x, y, z;
if (c == 'R')
{
x = 32768L*(pointer.y - oldy);
y = 32768L*(pointer.x - oldx);
z = 32768L*(pointer.z - oldz);
}
else
{
x = 3276L*(pointer.y - oldcy);
y = 3276L*(pointer.x - oldcx);
z = 3276L*(pointer.z - oldcz);
}
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
if (get_obj_flags(obj) & OBJ_HIGHLIGHTED) {
SEGMENT *s;
if ((s = get_object_owner(obj)) != NULL) {
rel_rot_segment(s, x, y, z);
update_segment(s);
}
}
refresh_display();
oldx = pointer.x; oldy = pointer.y; oldz = pointer.z;
pointer_read(&pointer);
}
while (pointer.buttons & 0x01) pointer_read(&pointer);
refresh_display();
break;
case 'A':
refresh_display();
poptext(surface_menu);
switch (toupper(getkey())) {
case 'N': surf = 0x0000; break;
case 'C': surf = 0x1000; break;
case 'M': surf = 0x2000; break;
case 'G': surf = 0x3000; break;
default: return 0;
}
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
{
int nv, np, i;
if (get_obj_flags(obj) & OBJ_HIGHLIGHTED) {
get_obj_info(obj, &nv, &np, NULL, 0);
for (i = 0; i < np; ++i) {
unsigned color;
get_poly_info(obj, i, &color, &nv, NULL, 0);
set_poly_color(obj, i, (color & 0xCFFF) | surf);
}
}
}
refresh_display();
break;
case 'P':
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
{
int nv, np, i;
if (get_obj_flags(obj) & OBJ_HIGHLIGHTED) {
get_obj_info(obj, &nv, &np, NULL, 0);
for (i = 0; i < np; ++i)
set_poly_color(obj, i, 0x8000 | paint);
}
}
refresh_display();
break;
case 'D':
refresh_display();
sprintf(buff, "Delete %d object%s! Are you sure?", nselected, (nselected > 1) ? "s" : "");
popmsg(buff);
if (toupper(getkey()) != 'Y') break;
refresh_display();
obj = first_in_objlist(objlist);
while (obj) {
OBJECT *nextobj;
nextobj = next_in_objlist(objlist, obj);
if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED)) {
if ((s = get_object_owner(obj)) != NULL)
seg_setrep(s, NULL);
remove_from_objlist(objlist, obj);
delete_obj(obj);
refresh_display();
}
if (bioskey(1)) {
popmsg("Aborted");
break;
}
obj = nextobj;
}
break;
case 'U':
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
{
set_obj_flags(obj, get_obj_flags(obj) & ~OBJ_HIGHLIGHTED);
unhighlight_obj(obj);
}
break;
case 'C':
refresh_display();
askfor("X,Y,Z offset: ", buff, 20);
if (buff[0] == '\0') break;
refresh_display();
sscanf(buff, "%ld,%ld,%ld", &dx, &dy, &dz);
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED) && (s = get_object_owner(obj)) != NULL) {
SEGMENT *n;
n = copy_segment(s, dx, dy, dz, dup_obj);
if (n) update_segment(n);
}
break;
case 'H':
refresh_display();
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED) && (s = get_object_owner(obj)) != NULL) {
detach_segment(s);
update_segment(s);
}
break;
case 'J':
refresh_display();
popmsg("Click on new parent");
while (!mouse_read(&mx, &my, &buttons));
refresh_display();
newparent = NULL;
do {
OBJECT *newobj;
do { mouse_read(&mx, &my, &buttons); } while (buttons == 0);
do { mouse_read(&mx, &my, &buttons); } while (buttons);
newobj = where_screen_pt(NULL, NULL, mx, my);
if (newobj)
if ((get_obj_flags(newobj) & OBJ_HIGHLIGHTED) == 0)
newparent = get_object_owner(newobj);
} while (newparent == NULL);
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED) && (s = get_object_owner(obj)) != NULL) {
attach_segment(s, newparent);
update_segment(s);
}
break;
case 'F':
refresh_display();
poptext(figure_menu);
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED) && (s = get_object_owner(obj)) != NULL)
break;
if (obj == NULL || s == NULL) {
popmsg("No objects selected!");
getkey();
return 0;
}
switch (toupper(getkey())) {
case 'F':
select_tree(find_root_segment(s)); /* and down again */
break;
case 'D':
refresh_display();
popmsg("Delete entire figure! Are you sure?");
if (toupper(getkey()) != 'Y') break;
refresh_display();
delete_segment(find_root_segment(s), zap_obj);
break;
case 'C':
refresh_display();
askfor("X,Y,Z offset: ", buff, 20);
if (buff[0] == '\0') break;
refresh_display();
sscanf(buff, "%ld,%ld,%ld", &dx, &dy, &dz);
s = copy_segment(find_root_segment(s), dx, dy, dz, dup_obj);
if (s) update_segment(s);
break;
case 'I':
count_tree(find_root_segment(s), &nsegs, &nverts, &npolys);
sprintf(buff, "%d segs, %d verts, %d polys", nsegs, nverts, npolys);
popmsg(buff);
getkey();
break;
case 'S':
refresh_display();
askfor("Filename: ", buff, 20);
if (buff[0] == '\0') break;
refresh_display();
if ((out = fopen(buff, "w")) == NULL) {
popmsg("Could not create file");
getkey();
break;
}
askfor("Comment: ", buff, 20);
if ((p = strchr(buff, ';')) != NULL) *p = '\0';
fprintf(out, "Comment = %s;\n", buff);
time(&now);
strcpy(buff, ctime(&now));
if ((p = strchr(buff, '\n')) != NULL) *p = '\0';
fprintf(out, "Comment = Saved from %s %s;\n", progname, buff);
writeseg(out, find_root_segment(s), 0);
fclose(out);
break;
default: return 0;
}
break;
default: break;
}
return 0;
}
do_mouse(int x, int y, unsigned buttons)
{
if (buttons & 0x01)
{
OBJECT *obj;
int pol, vert;
obj = where_screen_pt(&pol, NULL, x, y);
if (obj)
{
unsigned color;
int n;
get_poly_info(obj, pol, &color, &n, NULL, 0);
set_poly_color(obj, pol, color ^ 0x8000);
set_obj_flags(obj, get_obj_flags(obj) ^ OBJ_HIGHLIGHTED);
if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
highlight_obj(obj);
else
unhighlight_obj(obj);
redraw = 1;
}
else
{
popmsg("Not on any object");
delay(300);
}
redraw = 1;
while (buttons & 0x01) mouse_read(&x, &y, &buttons);
}
return 0;
}
/* find world coordinates of pointer based on given view */
void pointer_to_world(POINTER *p, VIEW *v, long *x, long *y, long *z)
{
MATRIX m,n;
*x = p->x;
*y = p->y;
*z = p->z;
make_matrix(m,v->tilt, v->pan, v->roll, v->ex, v->ey, v->ez);
inverse_matrix(m, n);
matrix_point(n,x,y,z);
}
static char *optmenu[] = {
"Background",
"Reflection",
"Logo",
NULL };
set_options()
{
poptext(optmenu);
switch (toupper(getkey())) {
case 'B': fancy_background = !fancy_background; break;
case 'R': reflection_pool = !reflection_pool;
if(reflection_pool) current_view->bottom = 160;
else current_view->bottom = 199;
break;
case 'L': show_logo = !show_logo; break;
default: break;
}
return 0;
}
load_logo(char *filename)
{
char far *buffer;
FILE *in;
if ((in = fopen(filename, "rb")) == NULL) return 0;
if (load_pcx(in, 3)) { /* some sort of problem loading it in */
fclose(in);
return 0;
}
fclose(in);
return 1; /* all is well... we have a logo */
}
resize_viewport()
{
int top, left, bottom, right;
unsigned buttons;
popmsg("Click top-left and drag");
do { mouse_read(&left, &top, &buttons); } while (buttons == 0);
while (buttons) {
while (!mouse_read(&right, &bottom, &buttons));
refresh_display();
vgabox(left, top, right, bottom, 15);
}
current_view->left = left; current_view->right = right;
current_view->top = top; current_view->bottom = bottom;
refresh_display();
return 0;
}
save_pcx_file()
{
char filename[100];
char far *buffer;
FILE *out;
refresh_display();
askfor("File to save to? ", filename, 20);
if (filename[0] == '\0') return 1;
refresh_display();
if ((out = fopen(filename, "wb")) == NULL) {
popmsg("Could not open file");
getkey();
return 3;
}
mouse_hide();
save_pcx(out, v_page);
mouse_show(v_page);
fclose(out);
return 0;
}
/* Some support routines */
static void center(char *s, int w)
{
int n;
if (strlen(s) == 0) return;
n = (w - strlen(s)) / 2;
memmove(&s[n], s, strlen(s)+1);
memset(s, ' ', n);
}
disp_status(VIEW *v)
{
char *text[9], a[80], b[80], c[80], d[80], e[80], f[80], g[80];
int w, i;
text[0] = a; text[1] = "";
text[2] = b; text[3] = c; text[4] = d; text[5] = e; text[6] = f;
text[7] = g; text[8] = NULL;
sprintf(a, "STATUS");
sprintf(b, "X = %ld Y = %ld Z = %ld", v->ex, v->ey, v->ez);
w = strlen(b);
sprintf(c, "Pan = %ld Tilt = %ld Roll = %ld ", v->pan/65536L, v->tilt/65536L, v->roll/65536L);
if (strlen(c) > w) w = strlen(c);
sprintf(d, "Zoom = %ld", v->zoom/65536L);
if (strlen(d) > w) w = strlen(d);
sprintf(e, "Hither = %ld Yon = %ld", v->hither, v->yon);
if (strlen(e) > w) w = strlen(e);
if (have_joystick)
{
joystick_read(&joy);
sprintf(f, "Joystick = %d,%d", joy.x, joy.y);
if (strlen(f) > w) w = strlen(f);
}
else
text[6] = NULL;
text[7] = NULL;
for (i = 0; text[i]; ++i) center(text[i], w);
poptext(text);
return 0;
}
static char *joyprompt1[] = {
" JOYSTICK CALIBRATION",
"",
" Please move the joystick",
" forward and left, and then",
" hit either joystick button",
NULL
};
static char *joyprompt2[] = {
" Thank you!",
"",
" Now please move the joystick",
"joystick back and right and then",
" hit either joystick button",
NULL
};
void joystick_calibration(joystick_data *joy)
{
if (have_joystick == 0) return;
if (have_joystick & 1) joystick_init(joy, 0);
else if (have_joystick & 2) joystick_init(joy, 1);
joystick_setscale(joy, 100);
poptext(joyprompt1);
joystick_scale(joy, 0);
poptext(joyprompt2);
joystick_scale(joy, 1);
}
disp_info(OBJLIST *objlist)
{
OBJECT *obj;
int nobjs = 0, nverts = 0, npolys = 0;
char buff[100];
for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(objlist, obj))
{
int nv, np;
get_obj_info(obj, &nv, &np, buff, sizeof(buff)-1);
++nobjs; nverts += nv; npolys += np;
}
sprintf(buff, "%d object%s, %d vertices, %d polygon%s", nobjs,
(nobjs > 1) ? "s" : "", nverts, npolys, (npolys > 1) ? "s" : "");
popmsg(buff);
getkey();
return 0;
}
collided(SEGMENT *hitter, SEGMENT *hit, long x, long y, long z)
{
putchar(7);
return 1;
}
#ifdef HAVEBOUNDS
extern MATRIX *get_seg_matrix();
check_coll(SEGMENT *seg, OBJLIST *olist)
{
long x, y, z;
OBJECT *obj;
SEGMENT *s;
void *p;
for (p = first_hotspot(seg, &x, &y, &z); p; p = next_hotspot(p, &x, &y, &z)) {
matrix_point(get_seg_matrix(seg), &x, &y, &z); /* convert point to world coordinates */
for (obj = first_in_objlist(olist); obj; obj = next_in_objlist(olist, obj))
if ((s = get_object_owner(obj)) != NULL)
if (pt_in_segment(s, x, y, z))
return collided(seg, s, x, y, z);
}
return 0;
}
#endif
static char *featmenu[] = {
"Select Surface type",
"Choose Color",
"Paint Polys",
NULL
};
static char *surfmenu[] = {
"Absolute",
"Cosine-lit",
"Metal",
"Glass",
NULL
};
void disp_palette()
{
int i, j, page;
page = mouse_hide();
for (i = 0; i < 16; i++)
for (j = 0; j < 16; j++)
user_box(j*10,i*8,j*10+9,i*8+8,i*16+j);
mouse_show(page);
}
static unsigned stype[] = { 0, 0x1000, 0x2000, 0x3000 };
unsigned paint = 1;
static unsigned surface = 0x1000;
static unsigned paintcolor = 1;
new_features()
{
int x, y, c, i;
unsigned buttons;
char buff[100];
if (!have_mouse)
{
popmsg("No mouse");
getkey();
return 3;
}
#ifdef MOUSING
c = menu(featmenu);
c = ("SCP")[c];
#else
poptext(featmenu);
c = toupper(getkey());
#endif
switch (c)
{
case 'S': /* select surface */
#ifdef MOUSING
i = menu(surfmenu);
surface = stype[i];
#else
poptext(surfmenu);
switch (toupper(getkey())) {
case 'N': surface = stype[0]; break;
case 'C': surface = stype[1]; break;
case 'M': surface = stype[2]; break;
case 'G': surface = stype[3]; break;
}
if (surface == 0)
paint = paintcolor;
else
paint = (surface | ((paintcolor << 4) & 0x0FF0) + 10); /* hue, brightness *16 */
#endif
refresh_display();
break;
case 'C': /* select color */
disp_palette();
while (mouse_read(&x, &y, &buttons) == 0);
disp_palette();
do {
do { mouse_read(&x, &y, &buttons); } while (!buttons);
do { mouse_read(&x, &y, &buttons); } while (buttons);
} while (y > 191);
paintcolor = 16*(y/8) + x/10;
if (surface == 0)
paint = paintcolor;
else
paint = (surface | ((paintcolor << 4) & 0x0FF0) + 10); /* hue, brightness *16 */
refresh_display();
break;
case 'P':
refresh_display();
do {
if (kbhit()) break;
while (mouse_read(&x, &y, &buttons) == 0 && !kbhit());
if (buttons & 0x01) {
OBJECT *obj;
int poly;
obj = where_screen_pt(&poly, NULL, x, y);
if (obj) {
set_poly_color(obj, poly, paint);
refresh_display();
}
}
} while (!(buttons & 0x02));
break;
default: break;
}
return 0;
}